package com.util.concurrent.countdownlatch;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;


/**
 * 一个或者多个线程，等待其他多个线程完成某件事情之后才能执行；
 * 这个例子，注释startSignal，发现，只要当player线程中latchStart为0，mian线程就和player并行了，
 * 如果不注释startSignal 发现Palyer线程需要等待 main线程将 startSignal为0 才可以
 */
public class CountDownLatchDemo {

    private static final int N = 5;

    public static void main(String[] args) {
        testCountDownLatch();
    }

    private static void testCountDownLatch() {
        CountDownLatch latchStart = new CountDownLatch(N);
        CountDownLatch latchOver = new CountDownLatch(N);
        CountDownLatch startSignal = new CountDownLatch(1);

        for (int i = 0; i < N; i++) {
            new Thread(new Player(i, latchStart, latchOver, startSignal)).start();
        }
        System.out.println("等待运动员准备好");
        try {
            latchStart.await(); //当5个player线程执行完成后，main线程才会走下去
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("开始比赛");
//        startSignal.countDown();
        try {
            latchOver.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("所有运动员都完成了比赛，比赛结束");
    }
}


class Player implements Runnable {
    private CountDownLatch latchStart;
    private CountDownLatch latchOver;
    private CountDownLatch startSignal;

    private int id;
    private static Random sRandom = new Random();

    public Player(int id, CountDownLatch latchStart, CountDownLatch lacthOver, CountDownLatch startSignal) {
        this.id = id;
        this.latchStart = latchStart;
        this.latchOver = lacthOver;
        this.startSignal = startSignal;
    }

    @Override
    public void run() {
        try {
            TimeUnit.SECONDS.sleep(sRandom.nextInt(2));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Player" + id + "准备好" + System.currentTimeMillis());
        this.latchStart.countDown();
//        try {
//            this.startSignal.await();
//        } catch(InterruptedException e) {
//            e.printStackTrace();
//        }
        System.out.println("Player" + id + "开始跑" + System.currentTimeMillis());
        long duration = sRandom.nextInt(5);
        try {
            TimeUnit.SECONDS.sleep(duration);
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Player" + id + "完成比赛, 耗时：" + duration);
        this.latchOver.countDown();
    }

}